#include "parser.h"
#include "common.h"
#include "utils.h"
#include "unicodeUtf8.h"
#include "Class.h"
#include <cstring>
#include <cctype>

struct keywordToken {
    const char *keyword;
    uint8_t length;
    TokenType token;
};  //关键字(保留字)结构

//关键字查找表
struct keywordToken keywordsToken[] = {
        {"var",      3, TOKEN_VAR},
        {"fun",      3, TOKEN_FUN},
        {"if",       2, TOKEN_IF},
        {"else",     4, TOKEN_ELSE},
        {"true",     4, TOKEN_TRUE},
        {"false",    5, TOKEN_FALSE},
        {"while",    5, TOKEN_WHILE},
        {"for",      3, TOKEN_FOR},
        {"break",    5, TOKEN_BREAK},
        {"continue", 8, TOKEN_CONTINUE},
        {"return",   6, TOKEN_RETURN},
        {"null",     4, TOKEN_NULL},
        {"class",    5, TOKEN_CLASS},
        {"is",       2, TOKEN_IS},
        {"static",   6, TOKEN_STATIC},
        {"this",     4, TOKEN_THIS},
        {"super",    5, TOKEN_SUPER},
        {"import",   6, TOKEN_IMPORT},
        {nullptr,    0, TOKEN_UNKNOWN}
};

// 判断start是否为关键字并返回相应的token
static TokenType IdOrkeyword(const char *start, uint32_t length) {
    uint32_t idx = 0;
    while (keywordsToken[idx].keyword != nullptr) {
        if (keywordsToken[idx].length == length && \
        memcmp(keywordsToken[idx].keyword, start, length) == 0) {
            return (TokenType)keywordsToken[idx].token;
        }
        idx++;
    }
    return TOKEN_ID;
}

Parser::Parser(VM *vm, const char *file, const char *sourceCode, ObjModule *objModule) {
    this->file = file;
    this->sourceCode = sourceCode;
    this->curChar = *this->sourceCode;
    this->nextCharPtr = this->sourceCode + 1;
    this->curToken.lineNo = 1;
    this->curToken.type = TOKEN_UNKNOWN;
    this->curToken.start = nullptr;
    this->curToken.length = 0;
    this->preToken = this->curToken;
    this->interpolationExpectRightParenNum = 0;
    this->vm = vm;
    this->curModule = objModule;
}

char Parser::LookAheadChar(Parser *parser) {
    return *parser->nextCharPtr;
}

void Parser::GetNextChar(Parser *parser) {
    parser->curChar = *parser->nextCharPtr++;
}

bool Parser::MatchNextChar(Parser *parser, char expectedChar) {
    if (Parser::LookAheadChar(parser) == expectedChar) {
        Parser::GetNextChar(parser);
        return true;
    }
    return false;
}

void Parser::SkipBlanks(Parser *parser) {
    while (isspace(parser->curChar)) {
        if (parser->curChar == '\n') {
            parser->curToken.lineNo++;
        }
        Parser::GetNextChar(parser);
    }
}

void Parser::ParseId(Parser *parser, TokenType type) {
    while (isalnum(parser->curChar) || parser->curChar == '_') {
        GetNextChar(parser);
    }

    //nextCharPtr会指向第1个不合法字符的下一个字符,因此-1
    auto length = (uint32_t) (parser->nextCharPtr - parser->curToken.start - 1);
    if (type != TOKEN_UNKNOWN) {
        parser->curToken.type = type;
    } else {
        parser->curToken.type = IdOrkeyword(parser->curToken.start, length);
    }
    parser->curToken.length = length;
}

void Parser::ParseUnicodeCodePoint(Parser *parser, ByteBuffer *buf) {
    uint32_t idx = 0;
    int value = 0;
    uint8_t digit = 0;

//获取数值,u后面跟着4位十六进制数字
    while (idx++ < 4) {
        GetNextChar(parser);
        if (parser->curChar == '\0') {
            LEX_ERROR(parser, "unterminated unicode!");
        }
        if (parser->curChar >= '0' && parser->curChar <= '9') {
            digit = parser->curChar - '0';
        } else if (parser->curChar >= 'a' && parser->curChar <= 'f') {
            digit = parser->curChar - 'a' + 10;
        } else if (parser->curChar >= 'A' && parser->curChar <= 'F') {
            digit = parser->curChar - 'A' + 10;
        } else {
            LEX_ERROR(parser, "invalid unicode!");
        }
        value = value * 16 | digit;
    }

    uint32_t byteNum = getByteNumOfEncodeUtf8(value);
    ASSERT(byteNum != 0, "utf8 encode bytes should be between 1 and 4!");

    //为代码通用, 下面会直接写buf->datas,在此先写入byteNum个0,以保证事先有byteNum个空间
    ByteBufferFillWrite(parser->vm, buf, 0, byteNum);

    //把value编码为utf8后写入缓冲区buf
    encodeUtf8(buf->datas + buf->count - byteNum, value);
}


void Parser::ParseHexNum(Parser *parser) {
    while (isxdigit(parser->curChar)) {
        GetNextChar(parser);
    }
}

void Parser::ParseDecNum(Parser *parser) {
    while (isdigit(parser->curChar)) {
        GetNextChar(parser);
    }

    //若有小数点
    if (parser->curChar == '.' && isdigit(LookAheadChar(parser))) {
        GetNextChar(parser);
        while (isdigit(parser->curChar)) { //解析小数点之后的数字
            GetNextChar(parser);
        }
    }
}

void Parser::ParseOctNum(Parser *parser) {
    while (parser->curChar >= '0' && parser->curChar < '8') {
        GetNextChar(parser);
    }
}

void Parser::ParseNum(Parser *parser) {

    double sum;

    //十六进制的0x前缀
    if (parser->curChar == '0' && MatchNextChar(parser, 'x')) {
        GetNextChar(parser);  //跳过'x'
        ParseHexNum(parser);   //解析十六进制数字
        sum = (double)strtol(parser->curToken.start, nullptr, 16);
        parser->curToken.value = NUM_TO_VALUE(sum);
    } else if (parser->curChar == '0' && isdigit(LookAheadChar(parser))) {  // 八进制
        ParseOctNum(parser);
        sum = (double)strtol(parser->curToken.start, nullptr, 8);
        parser->curToken.value = NUM_TO_VALUE(sum);
    } else {      //解析十进制
        ParseDecNum(parser);
        parser->curToken.value = NUM_TO_VALUE(strtod(parser->curToken.start, nullptr));
    }
    //nextCharPtr会指向第1个不合法字符的下一个字符,因此-1
    parser->curToken.length =
            (uint32_t) (parser->nextCharPtr - parser->curToken.start - 1);
    parser->curToken.type = TOKEN_NUM;
}

void Parser::ParseString(Parser *parser) {
    ByteBuffer str;
    ByteBufferInit(&str);
    while (true) {
        GetNextChar(parser);

        if (parser->curChar == '\0') {
            LEX_ERROR(parser, "unterminated string!");
        }

        if (parser->curChar == '"') {
            parser->curToken.type = TOKEN_STRING;
            break;
        }

        if (parser->curChar == '%') {
            if (!MatchNextChar(parser, '(')) {
                LEX_ERROR(parser, "'%' should followed by '('!");
            }
            if (parser->interpolationExpectRightParenNum > 0) {
                COMPILE_ERROR(parser, "sorry, I don`t support nest interpolate expression!");
            }
            parser->interpolationExpectRightParenNum = 1;
            parser->curToken.type = TOKEN_INTERPOLATION;
            break;
        }

        if (parser->curChar == '\\') {   //处理转义字符
            GetNextChar(parser);
            switch (parser->curChar) {
                case '0':
                    ByteBufferAdd(parser->vm, &str, '\0');
                    break;
                case 'a':
                    ByteBufferAdd(parser->vm, &str, '\a');
                    break;
                case 'b':
                    ByteBufferAdd(parser->vm, &str, '\b');
                    break;
                case 'f':
                    ByteBufferAdd(parser->vm, &str, '\f');
                    break;
                case 'n':
                    ByteBufferAdd(parser->vm, &str, '\n');
                    break;
                case 'r':
                    ByteBufferAdd(parser->vm, &str, '\r');
                    break;
                case 't':
                    ByteBufferAdd(parser->vm, &str, '\t');
                    break;
                case 'u':
                    ParseUnicodeCodePoint(parser, &str);
                    break;
                case '"':
                    ByteBufferAdd(parser->vm, &str, '"');
                    break;
                case '\\':
                    ByteBufferAdd(parser->vm, &str, '\\');
                    break;
                default:
                    LEX_ERROR(parser, "unsupport escape \\%c", parser->curChar);
                    break;
            }
        } else {   //普通字符
            ByteBufferAdd(parser->vm, &str, parser->curChar);
        }
    }

    //用识别到的字符串新建字符串对象存储到curToken的value中
    auto *objString = new ObjString(parser->vm, (const char*)str.datas, str.count);
    parser->curToken.value = OBJ_TO_VALUE(objString);
    ByteBufferClear(parser->vm, &str);
}

void Parser::SkipAline(Parser *parser) {
    GetNextChar(parser);
    while (parser->curChar != '\0') {
        if (parser->curChar == '\n') {
            parser->curToken.lineNo++;
            GetNextChar(parser);
            break;
        }
        GetNextChar(parser);
    }
}

void Parser::SkipComment(Parser *parser) {
    char nextChar = LookAheadChar(parser);
    if (parser->curChar == '/') {  // 行注释
        SkipAline(parser);
    } else {   // 区块注释
        while (nextChar != '*' && nextChar != '\0') {
            GetNextChar(parser);
            if (parser->curChar == '\n') {
                parser->curToken.lineNo++;
            }
            nextChar = LookAheadChar(parser);
        }
        if (MatchNextChar(parser, '*')) {
            if (!MatchNextChar(parser, '/')) {   //匹配*/
                LEX_ERROR(parser, "expect '/' after '*'!");
            }
            GetNextChar(parser);
        } else {
            LEX_ERROR(parser, "expect '*/' before file end!");
        }
    }
    SkipBlanks(parser);  //注释之后有可能会有空白字符
}

void Parser::GetNextToken(Parser *parser) {
    parser->preToken = parser->curToken;
    SkipBlanks(parser);  // 跳过待识别单词之前的空格
    parser->curToken.type = TOKEN_EOF;
    parser->curToken.length = 0;
    parser->curToken.start = parser->nextCharPtr - 1;
    while (parser->curChar != '\0') {
        switch (parser->curChar) {
            case ',':
                parser->curToken.type = TOKEN_COMMA;
                break;
            case ':':
                parser->curToken.type = TOKEN_COLON;
                break;
            case '(':
                if (parser->interpolationExpectRightParenNum > 0) {
                    parser->interpolationExpectRightParenNum++;
                }
                parser->curToken.type = TOKEN_LEFT_PAREN;
                break;
            case ')':
                if (parser->interpolationExpectRightParenNum > 0) {
                    parser->interpolationExpectRightParenNum--;
                    if (parser->interpolationExpectRightParenNum == 0) {
                        ParseString(parser);
                        break;
                    }
                }
                parser->curToken.type = TOKEN_RIGHT_PAREN;
                break;
            case '[':
                parser->curToken.type = TOKEN_LEFT_BRACKET;
                break;
            case ']':
                parser->curToken.type = TOKEN_RIGHT_BRACKET;
                break;
            case '{':
                parser->curToken.type = TOKEN_LEFT_BRACE;
                break;
            case '}':
                parser->curToken.type = TOKEN_RIGHT_BRACE;
                break;
            case '.':
                if (MatchNextChar(parser, '.')) {
                    parser->curToken.type = TOKEN_DOT_DOT;
                } else {
                    parser->curToken.type = TOKEN_DOT;
                }
                break;
            case '=':
                if (MatchNextChar(parser, '=')) {
                    parser->curToken.type = TOKEN_EQUAL;
                } else {
                    parser->curToken.type = TOKEN_ASSIGN;
                }
                break;
            case '+':
                parser->curToken.type = TOKEN_ADD;
                break;
            case '-':
                parser->curToken.type = TOKEN_SUB;
                break;
            case '*':
                parser->curToken.type = TOKEN_MUL;
                break;
            case '/':
                //跳过注释'//'或'/*'
                if (MatchNextChar(parser, '/') || MatchNextChar(parser, '*')) {
                    SkipComment(parser);

                    //重置下一个token起始地址
                    parser->curToken.start = parser->nextCharPtr - 1;

                    continue;
                } else {         // '/'
                    parser->curToken.type = TOKEN_DIV;
                }
                break;
            case '%':
                parser->curToken.type = TOKEN_MOD;
                break;
            case '&':
                if (MatchNextChar(parser, '&')) {
                    parser->curToken.type = TOKEN_LOGIC_AND;
                } else {
                    parser->curToken.type = TOKEN_BIT_AND;
                }
                break;
            case '|':
                if (MatchNextChar(parser, '|')) {
                    parser->curToken.type = TOKEN_LOGIC_OR;
                } else {
                    parser->curToken.type = TOKEN_BIT_OR;
                }
                break;
            case '~':
                parser->curToken.type = TOKEN_BIT_NOT;
                break;
            case '?':
                parser->curToken.type = TOKEN_QUESTION;
                break;
            case '>':
                if (MatchNextChar(parser, '=')) {
                    parser->curToken.type = TOKEN_GREATE_EQUAL;
                } else if (MatchNextChar(parser, '>')) {
                    parser->curToken.type = TOKEN_BIT_SHIFT_RIGHT;
                } else {
                    parser->curToken.type = TOKEN_GREATE;
                }
                break;
            case '<':
                if (MatchNextChar(parser, '=')) {
                    parser->curToken.type = TOKEN_LESS_EQUAL;
                } else if (MatchNextChar(parser, '<')) {
                    parser->curToken.type = TOKEN_BIT_SHIFT_LEFT;
                } else {
                    parser->curToken.type = TOKEN_LESS;
                }
                break;
            case '!':
                if (MatchNextChar(parser, '=')) {
                    parser->curToken.type = TOKEN_NOT_EQUAL;
                } else {
                    parser->curToken.type = TOKEN_LOGIC_NOT;
                }
                break;

            case '"':
                ParseString(parser);
                break;

            default:
                //处理变量名及数字
                //进入此分支的字符肯定是数字或变量名的首字符
                //后面会调用相应函数把其余字符一并解析
                //不过识别数字需要一些依赖,目前暂时去掉

                //首字符是字母或'_'则是变量名
                if (isalpha(parser->curChar) || parser->curChar == '_') {
                    ParseId(parser, TOKEN_UNKNOWN);  //解析变量名其余的部分
                } else if (isdigit(parser->curChar)) {
                    ParseNum(parser);
                } else {
                    if (parser->curChar == '#' && MatchNextChar(parser, '!')) {
                        SkipAline(parser);
                        parser->curToken.start = parser->nextCharPtr - 1;  //重置下一个token起始地址
                        continue;
                    }
                    LEX_ERROR(parser, "unsupport char: \'%c\', quit.", parser->curChar);
                }
                return;
        }
        //大部分case的出口
        parser->curToken.length = (uint32_t) (parser->nextCharPtr - parser->curToken.start);
        GetNextChar(parser);
        return;
    }
}

bool Parser::MatchToken(Parser *parser, TokenType expected) {
    if (parser->curToken.type == expected) {
        GetNextToken(parser);
        return true;
    }
    return false;
}

void Parser::ConsumeCurToken(Parser *parser, TokenType expected, const char *errMsg) {
    if (parser->curToken.type != expected) {
        COMPILE_ERROR(parser, errMsg);
    }
    GetNextToken(parser);
}

void Parser::ConsumeNextToken(Parser *parser, TokenType expected, const char *errMsg) {
    GetNextToken(parser);
    if (parser->curToken.type != expected) {
        COMPILE_ERROR(parser, errMsg);
    }
}

Parser::Parser() {

}
